//
//  smcJaikuAPI+contacts.m
//  juhu
//
//  Created by Christian Martick on 27.07.07.
//  Copyright 2007 Christian Martick. All rights reserved.
//
//	jaiku api - recent posts of all jaiku users - public timeline sort of
//
//	this objects handle the users contacts posts using rss feed
//
//	Copyright (C) 2007 Christian Martick, http://juhu-mac.blogspot.com
//
//	Permission is hereby granted, free of charge, to any person obtaining a copy
//	of this software and associated documentation files (the "Software"), to deal
//	in the Software without restriction, including without limitation the rights
//	to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//	copies of the Software, and to permit persons to whom the Software is
//	furnished to do so, subject to the following conditions:
//
//	The above copyright notice and this permission notice shall be included in
//	all copies or substantial portions of the Software.
//
//	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//	OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
//	THE SOFTWARE.

#import "smcJaikuAPI.h"

@implementation smcJaikuAPI (contacts)

- (NSError *) _do: (int) index withContact: (NSString *) nickname
{
	// does the actual work of adding/removing
	// index = 0 -> add, index = 1 -> remove
	
	// queries,  error information and so on depening on add or remove
	NSString *baseCommand;
	NSString *urlEndString;
	NSError *myError;
	if (index == 0)
	{
		//add
		baseCommand = @"http://jaiku.com/contacts/manage?add=";
		urlEndString = @"&amp;redirect";
		myError = [NSError errorWithDomain: @"jaikuContactAdd"
			code: kSmcErrorContactAddFailed
			userInfo: [NSDictionary dictionaryWithObjectsAndKeys: 
				@"Could not add to Contacts", @"errorAbstract",
				@"Adding this user to your contacts failed, sorry.", @"errorText", NULL]];
	}
	else
	{
		baseCommand = @"http://jaiku.com/contacts/manage?remove=";
		urlEndString = @"\">";
		myError = [NSError errorWithDomain: @"jaikuContactRemove"
			code: kSmcErrorContactRemoveFailed
			userInfo: [NSDictionary dictionaryWithObjectsAndKeys: 
				@"Could not remove contact", @"errorAbstract",
				@"Removing this user from your contacts failed, sorry.", @"errorText", NULL]];
	}
	
	//check if _username and password are neq nil
	if ((_username == nil) || (_personalKey == nil))
		return [self missingUsernameOrPasswordErrorWithDomain: [myError domain]];
	
	NSURL *url;
	NSURLResponse *response;
	NSError *error;
	
	//okay, built url
	url = [NSURL URLWithString: [NSString stringWithFormat: @"http://%@.jaiku.com?user=%@&personal_key=%@", nickname, _username, _personalKey]];

	NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL: url
			cachePolicy: NSURLRequestReloadIgnoringCacheData timeoutInterval:10];
	   
	[request addValue: JUHUCLIENT_VERSION forHTTPHeaderField: @"User-Agent"];
	
	NSData *data = [NSURLConnection sendSynchronousRequest: request
			returningResponse: &response
			error: &error];

	NSMutableString *htmlString = [self makeCleanUTF8MutableStringFromData: data];
	
	if (htmlString == nil)
		return myError;

	//find base command
	NSRange range = [htmlString rangeOfString: baseCommand];
	if (range.location == NSNotFound)
		return myError;
	
	//cut down
	[htmlString deleteCharactersInRange: NSMakeRange( 0, range.location)];
	
	//end of url
	range = [htmlString rangeOfString: urlEndString];
	if (range.location == NSNotFound)
		return myError;
	
	//cut down
	htmlString = [NSMutableString stringWithString: [htmlString substringToIndex: range.location]];	
	
	//some specific replacements...
	if (index == 0)
	{
		//replace
		[htmlString replaceOccurrencesOfString: @"&amp;" withString:@"&" options: NSBackwardsSearch range: NSMakeRange( 0,[htmlString length])];
	} else
	{
		//remove redirect: &amp;redirect_to=http://???.jaiku.com&amp;
		NSString *tmpRedirect = [NSString stringWithFormat: @"&amp;redirect_to=http://%@.jaiku.com&amp;", nickname];
		[htmlString replaceOccurrencesOfString: tmpRedirect withString: @"&" options: NSBackwardsSearch range: NSMakeRange( 0, [htmlString length])];
	}
	
	//create url string & url
	NSURL *finalURL = [NSURL URLWithString: [NSString stringWithFormat: @"%@&user=%@&personal_key=%@", htmlString, _username, _personalKey]];
	if (finalURL == nil)
		return myError;
			
	//go for it
	request = [NSMutableURLRequest requestWithURL: finalURL
				cachePolicy: NSURLRequestReloadIgnoringCacheData timeoutInterval:15];
		   
	[request addValue: JUHUCLIENT_VERSION forHTTPHeaderField: @"User-Agent"];
		
	[NSURLConnection sendSynchronousRequest: request
				returningResponse: &response
				error: &error];

	// finally the post didn't work out?
	if (error != nil)
		return [NSError errorWithDomain: [myError domain]
			code: [myError code]
			userInfo: [NSDictionary dictionaryWithObjectsAndKeys: 
				[[myError userInfo] objectForKey: @"errorAbstract"], @"errorAbstract",
				[[myError userInfo] objectForKey: @"errorText"], @"errorText", 
				error, @"urlConnectionError", NULL]];
	else
		return nil;

}

- (NSArray *) friends
{
	//give all contacts, including channels...
	return _contacts;
}

- (NSArray *) channels
{
	//return all channels
	NSMutableArray *tmp = [NSMutableArray arrayWithCapacity: 100];
	
	for (int i = 0; i < [_contacts count]; i++)
	{
		if ([[[[_contacts objectAtIndex: i] objectForKey: @"nick"] substringToIndex: 1] isEqualToString: @"#"])
			[tmp addObject: [[[_contacts objectAtIndex: i] objectForKey: @"nick"] substringFromIndex: 1]];
	}

	return tmp;
}

- (BOOL) isFriend: (NSString *) nickname
{
	//look in contacts if nick is in there, if it is return yes, else return no

	if ((_contacts != nil) && ([_contacts count] > 0))
	{
		for (int i = 0; i < [_contacts count]; i++)
		{
			if ([[_contacts objectAtIndex: i] objectForKey: kSmcEntryKeyNick] != nil)
				if ([[[_contacts objectAtIndex: i] objectForKey: kSmcEntryKeyNick] isEqualToString: nickname])
					return YES;
		}
	}
	
	return NO;
}

- (NSError *) addAsFriend: (NSString *) nickname
{
	//add a user
	
	//check if not already in contacts
	if ([self isFriend: nickname])
		return [NSError errorWithDomain: @"jaikuContactAdd"
			code: kSmcErrorContactCantAddBecauseIs 
			userInfo: [NSDictionary dictionaryWithObjectsAndKeys: 
				@"Could not add to Contacts", @"errorAbstract",
				@"Since this user is already a friend, it could not be added", @"errorText", NULL]];
	
	return [self _do: 0 withContact: nickname];
}

- (NSError *) removeFriend: (NSString *) nickname
{
	//remove a user
	
	//check if in contacts
	if (![self isFriend: nickname])
		return [NSError errorWithDomain: @"jaikuContactRemove"
			code: kSmcErrorContactCantRemoveBecauseIsnt
			userInfo: [NSDictionary dictionaryWithObjectsAndKeys: 
				@"Could not remove the contact", @"errorAbstract",
				@"Since this user is not a friend, it could not be removed", @"errorText", NULL]];
	
	return [self _do: 1 withContact: nickname];
}

- (NSError *) updateFriendListSynchronously: (BOOL) flag
{
	//kickoff download of json contact feed
	//if flag YES, then do it sync otherwise async
	
	//check if _username and password are neq nil
	if ((_username == nil) || (_personalKey == nil))
		return [self missingUsernameOrPasswordErrorWithDomain: @"jaikuContactUpdate"];
	
	NSURL *url = [NSURL URLWithString: 
			[NSString stringWithFormat: @"http://%@.jaiku.com/json?user=%@&personal_key=%@", _username, _username, _personalKey]];

	//don't run a second update
	if (_doingContactUpdate)
		return [NSError errorWithDomain: @"jaikuContactUpdate"
			code: kSmcErrorCommentDoingUpdating
			userInfo: [NSDictionary dictionaryWithObjectsAndKeys: 
				@"Could not update contacts", @"errorAbstract",
				@"Since there is already an updating taking place, no new one could be started", @"errorText", NULL]];

	_contactUpdateError = NO;

	//sync or async?
	if (flag)
	{
		//sync download
		NSURLResponse *response;
		NSError *error;
		_doingContactUpdate = YES;
	
		NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL: url
				cachePolicy: NSURLRequestReloadIgnoringCacheData timeoutInterval:10];
		   
		[request addValue: JUHUCLIENT_VERSION forHTTPHeaderField: @"User-Agent"];
		
		NSData *data = [NSURLConnection sendSynchronousRequest: request
				returningResponse: &response
				error: &error];
		
		if (error != nil)			
		{
			_doingContactUpdate = NO;
			return [NSError errorWithDomain: @"jaikuContactUpdate"
				code: kSmcErrorContactNoFeed
				userInfo: [NSDictionary dictionaryWithObjectsAndKeys: 
					@"Could not update contacts", @"errorAbstract",
					@"The request to update the contact list failed", @"errorText", 
					error, @"urlConnectionError", NULL]];;
		}
		
		//everything seems fine, so process data
		if (data != nil)
			[self downloadFromURL: url didFinishWithData: data 
				andInfo: [NSDictionary dictionaryWithObjectsAndKeys: 
						@"contactUpdate", @"kind", NULL]];
		else
		{
			//...or not so fine
			_doingContactUpdate = NO;
			return [NSError errorWithDomain: @"jaikuContactUpdate"
				code: kSmcErrorContactNoFeed
				userInfo: [NSDictionary dictionaryWithObjectsAndKeys: 
				@"Could not update contacts", @"errorAbstract",
				@"Since the downloaded data does not seem to be a proper feed, the contact list could not be updated", @"errorText", NULL]]; 
		}
		
		//update done, parsing done, there could be an error while
		//parse and convert
		if (_contactUpdateError)
			return [NSError errorWithDomain: @"jaikuContactUpdate"
				code: kSmcErrorContactNoFeed
				userInfo: [NSDictionary dictionaryWithObjectsAndKeys: 
				@"Could not update contacts", @"errorAbstract",
				@"Since the downloaded data does not seem to be a proper feed, the contact list could not be updated", @"errorText", NULL]]; 
		else
			return nil;				
	} else
	{
		//async download setup
		_doingContactUpdate = YES;		
		smcAsyncConnection *_tmp = [[[smcAsyncConnection alloc] init] autorelease];
		[_tmp setDelegate: self];
		
		if (![_tmp beginDownloadFromURL: url withTimout: 15 userAgent: JUHUCLIENT_VERSION 
			andInfo: [NSDictionary dictionaryWithObjectsAndKeys: 
						@"contactUpdate", @"kind", NULL]])
		{
			_doingContactUpdate = NO;
			_contactUpdateError = YES;
			return [NSError errorWithDomain: @"jaikuContactUpdate"
				code: kSmcErrorContactNoFeed
				userInfo: [NSDictionary dictionaryWithObjectsAndKeys: 
				@"Could not update contacts", @"errorAbstract",
				@"Since the downloaded data does not seem to be a proper feed, the contact list could not be updated", @"errorText", NULL]];
		}
		return nil;
	}
}


@end
